numpy高级教程之np.where和np.piecewise
进入正文
1.1
numpy.
where
(condition[, x, y])
If only condition is given, return condition.nonzero()
.
Parameters: |
condition : array_like, bool When True, yield x, otherwise yield y. x, y : array_like, optional Values from which to choose. x, y and condition need to be broadcastable to some shape. |
---|---|
Returns: |
out : ndarray or tuple of ndarrays If both x and y are specified, the output array contains elements of x where condition is True, and elements from y elsewhere. If only condition is given, return the tuple |
解释:
condition:该函数可以接受一个必选参数condition,注意该参数必须是array型的,只不过元素是true或者是false
x,y是可选参数:如果条件为真,则返回x,如果条件为false,则返回y,注意condition、x、y三者必须要能够“广播”到相同的形状
返回结果:返回的是数组array或者是元素为array的tuple元组,如果只有一个condition,则返回包含array的tuple,如果是有三个参数,则返回一个array。后面会详细介绍。
1.2
1.2.1 当condition是一维时
a = np.array([2,4,6,8,10])
a_where=np.where(a > 5) # 返回索引,a>5得到的是array。
print(a_where)
print(a[np.where(a > 5)]) # 等价于 a[a>5],布尔索引
b=np.array([False,True,False,True,False])
print(np.where(b))
打印的结果为如下:
(array([2, 3, 4], dtype=int64),)
#返回的2,3,4即对应于元素大于5(True)的元素的索引位置,即第3、4、5个元素,以array得形式返回。
---------------------------------
[ 6 8 10]
---------------------------------
(array([1, 3], dtype=int64),)
#返回元素中为True的元素所对应的位置索引,即第2个和第4个元素,以array的形式返回。
1.2.2 当condition是二维时
a=np.array([[1,2,3,4,5],[2,3,4,5,6],[3,4,5,6,7],[4,5,6,7,8]]) #二维数组
a_where=np.where(a>3)
print(a_where)
print(a[a_where])
运行结果为:
(array([0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3], dtype=int64), array([3, 4, 2, 3, 4, 1, 2, 3, 4, 0, 1, 2, 3, 4], dtype=int64))
[4 5 4 5 6 4 5 6 7 4 5 6 7 8]
对于第一个返回的结果,我们可以看到,它返回的是一个元组tuple,元组的第一个元素是一个array,它的值来源于满足条件的元素的行索引,两个0行的,三个1行的,四个2行的,五个3行的;元祖的第二个元素也是一个array,它的值来源于满足条件的元素的列索引。
再看一个例子
b=np.where([[0, 3,2], [0,4, 0]])
print(b)
返回结果为:
(array([0, 0, 1], dtype=int64), array([1, 2, 1], dtype=int64))
#返回的依然是一个元组tuple,第一个元素是一个array,来源于行,第二个元素也是一个array,来源于列。注意,这一没有删选条件啊,因为where的参数就是b而不是什么,b>1,b>2之类的布尔表达式,那是怎么回事呢,实际上,它是经过进一步处理了的,将0元素看成是false,将大于0的全部当成是true,与下面的运行结果是完全等价的。
c=np.array([[False,True,True],[False,True,False]])
print(np.where(c))
输出结果为:
(array([0, 0, 1], dtype=int64), array([1, 2, 1], dtype=int64))
#同上面完全一样
1.2.3 当condition是多维时
a=[
[
[1,2,3],[2,3,4],[3,4,5]
],
[
[0,1,2],[1,2,3],[2,3,4]
]
]
a=np.array(a)
print(a.shape) #形状为(2,3,3)
a_where=np.where(a>3)
print(a_where)
运行结果为:
(array([0, 0, 0, 1], dtype=int64),
array([1, 2, 2, 2], dtype=int64),
array([2, 1, 2, 2], dtype=int64))
同上,返回的是一个元组,第一个元素是array类型,来源于第一个维度满足条件的索引,第二个元素是array类型,来源于第二个维度满足条件的索引,第三个元素是array类型,来源于第三个维度满足条件的索引。
本节总结
总结:
针对上面的讲述,where的作用就是返回一个数组中满足条件的元素(True)的索引,且返回值是一个tuple类型,tuple的每一个元素均为一个array类型,array的值即对应某一纬度上的索引。
在之给定一个参数condition的时候,np.where(condition)和condition.nonzero()是完全等价的。
1.3
a = np.arange(10)
a_where=np.where(a,1,-1)
print(a_where)
a_where_1=np.where(a > 5,1,-1)
print(a_where_1)
b=np.where([[True,False], [True,True]], #第一个参数
[[1,2], [3,4]], #第二个参数
[[9,8], [7,6]] #第三个参数
)
print(b)
运行结果为:
[-1 1 1 1 1 1 1 1 1 1]
[-1 -1 -1 -1 -1 -1 1 1 1 1]
[[1 8]
[3 4]]
对于第一个结果,因为只有第一个是0,即false,故而用-1替换了,后面的都大于0,即true,故而用1替换了
对于第二个结果,前面的6个均为false,故而用-1替换,后面的四个为true,则用1替换
对于第三个结果,
--------------------------------------
第一个True对应的索引位置为(0,0),true在第二个参数中寻找,(0,0)对应于元素1
第二个false对应的索引位置为(0,1),false在第三个参数中寻找,(0,1)对应于元素8
第三个True对应的索引位置为(1,0),true在第二个参数中寻找,(0,0)对应于元素3
第四个True对应的索引位置为(1,1),true在第二个参数中寻找,(0,0)对应于元素4
本节总结
总结:在使用三个参数的时候,要注意,condition、x、y必须具有相同的维度或者是可以广播成相同的形状,否则会报错,它返回的结果是一个列表,同原始的condition具有相同的维度和形状。
总结:通过上面的讲述,已经了解到了np.where函数的强大之处,它的本质上就是选择操作,但是如果我们自己编写条件运算,使用if-else或者是列表表达式这样的语句,效率低下,故而推荐使用np.where
Next
np.piecewise也和前面讲过的where、select、choose一样,属于高级应用,而且实现的功能也有类似的,即根据相关的条件,进行筛选,然后对漫步不同条件的元素进行相关的操作,这个操作可以来源与函数、lambda表达式等,并得到新的结果。
2.1
numpy.
piecewise
(x, condlist, funclist, *args, **kw)
Evaluate a piecewise-defined function.
Given a set of conditions and corresponding functions, evaluate each function on the input data wherever its condition is true.
Parameters: |
x : ndarray or scalar The input domain. condlist : list of bool arrays or bool scalars Each boolean array corresponds to a function in funclist. Wherever condlist[i] is True, funclist[i](x) is used as the output value. Each boolean array in condlist selects a piece of x, and should therefore be of the same shape as x. The length of condlist must correspond to that of funclist. If one extra function is given, i.e. if funclist : list of callables, f(x,*args,**kw), or scalars Each function is evaluated over x wherever its corresponding condition is True. It should take a 1d array as input and give an 1d array or a scalar value as output. If, instead of a callable, a scalar is provided then a constant function ( args : tuple, optional Any further arguments given to kw : dict, optional Keyword arguments used in calling |
---|---|
Returns: |
out : ndarray The output is the same shape and type as x and is found by calling the functions in funclist on the appropriate portions of x, as defined by the boolean arrays in condlist. Portions not covered by any condition have a default value of 0. |
参数一 x:表示要进行操作的对象
参数二:condlist,表示要满足的条件列表,可以是多个条件构成的列表
参数三:funclist,执行的操作列表,参数二与参数三是对应的,当参数二为true的时候,则执行相对应的操作函数。
返回值:返回一个array对象,和原始操作对象x具有完全相同的维度和形状
2.2
2.2.1 案例一
x = np.arange(0,10)
print(x)
xx=np.piecewise(x, [x < 4, x >= 6], [-1, 1])
print(xx)
运行结果为:
[0 1 2 3 4 5 6 7 8 9]
[-1 -1 -1 -1 0 0 1 1 1 1]
即将元素中小于4的用-1替换掉,大于等于6的用1替换掉,其余的默认以0填充。其实这里的替换和填充就是function,这不过这里的function跟简单粗暴,都用同一个数替换了。实际上,上面的代码完全等价于下面的代码:
x = np.arange(0,10)
def func1(y):
return -1
def func2(y):
return 1
xxx=np.piecewise(x, [x < 4, x >= 6], [func1, func2])
print(xxx)
运行结果为:
[-1 -1 -1 -1 0 0 1 1 1 1] #同上面一样
2.2.2 案例二:通过定义操作函数
x = np.arange(0,10)
#元素进行平方
def func2(y):
return 1ef func1(y):
return y**2
#元素乘以100
def func2(y):
return y*100
xxx=np.piecewise(x, [x < 4, x >= 6], [func1, func2])
print(xxx)
运行结果为:
[ 0 1 4 9 0 0 600 700 800 900]
2.2.3 案例三:通过定义lambda表达式
x = np.arange(0,10)
xxxx=np.piecewise(x, [x < 4, x >= 6], [lambda x:x**2, lambda x:x*100])
print(xxxx)
运行结果为:
[ 0 1 4 9 0 0 600 700 800 900]
本节总结
总结:piecewise的处理方法快捷方便,比自己编写循环和条件语句的执行效率高很多,推荐多使用。
Next
numpy的where和piecewise函数,包括前面的choose和select函数都是特别重要的,特别是对于数据分析处理方面,适用于定义的高级函数比自己通过编写python代码使用循环以及条件语句执行效率更加高效,但是很少有文章从头到尾、从定义到应用详细介绍相关的文档,故而写了这两篇文章,另一片参见前面,希望对有需要的人有所帮助,有任何建议也建议积极反馈,在此表示感谢!
END
往期回顾
●python可视化——详解matplotlib的配置文件以及配置方式